package com.zqxx.examine.portal.security.filter;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.StringUtils;

import com.zqxx.examine.model.exam.Exam;
import com.zqxx.examine.model.exam.ExamHistory;
import com.zqxx.examine.portal.security.StandardPasswordEncoderForSha1;
import com.zqxx.examine.portal.security.UserInfo;
import com.zqxx.examine.portal.service.ExamService;

public class AuthenticationFilter
  extends UsernamePasswordAuthenticationFilter
{
  public static final String VALIDATE_CODE = "validate_code";
  public static final String USERNAME = "j_username";
  public static final String PASSWORD = "j_password";
  public static final String SERI_NO = "j_seri_no";
  public static final String FLAG = "j_flag";
  private static Logger log = Logger.getLogger(AuthenticationFilter.class);
  @Autowired
  public ExamService examService;
  
  public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
    throws AuthenticationException
  {
    String seriNo = obtainSeriNoParameter(request);
    String username = obtainUsername(request);
    String password = obtainPassword(request);
    String flag = obtainFlagParameter(request);
    

    String sh1Password = password + "{" + username + "}";
    PasswordEncoder passwordEncoder = new StandardPasswordEncoderForSha1();
    String result = passwordEncoder.encode(sh1Password);
    log.info(result);
    if (!request.getMethod().equals("POST")) {
      throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
    }
    if ((seriNo != null) && (!"".equals(seriNo)))
    {
      ExamHistory hist = this.examService.getUserExamHistBySeriNo(seriNo, 1);
      if (hist != null)
      {
        username = hist.getUserName();
        password = "";
      }
      else
      {
        throw new AuthenticationServiceException("准考证号码错误！");
      }
      Exam exam = this.examService.getExamById(hist.getExamId());
      if (exam.getApproved() == 0) {
        throw new AuthenticationServiceException("无法参加一个未审核通过的考试！");
      }
      Date now = new Date();
      if ((exam.getEffTime().after(now)) || (exam.getExpTime().before(now))) {
        throw new AuthenticationServiceException("不在考试时间范围内，不允许使用准考证！");
      }
      if (hist.getApproved() == 0) {
        throw new AuthenticationServiceException("考试申请未审核，请联系管理员！");
      }
      if (hist.getApproved() == 2) {
        throw new AuthenticationServiceException("考试申请审核未通过，不能参加考试！");
      }
      UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
      setDetails(request, authRequest);
      Authentication authentication = null;
      try
      {
        authentication = getAuthenticationManager().authenticate(authRequest);
        UserInfo userInfo = (UserInfo)authentication.getPrincipal();
        userInfo.setHistId(hist.getHistId());
        userInfo.setExamId(hist.getExamId());
        userInfo.setExamPaperId(hist.getExamPaperId());
      }
      catch (Exception e)
      {
        e.printStackTrace();
      }
      return authentication;
    }
    if ("1".equals(flag)) {
      throw new AuthenticationServiceException("准考证号码错误！");
    }
    if ((!"".equals(username)) && ("".equals(password))) {
      throw new AuthenticationServiceException("请输入密码！");
    }
    UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
    setDetails(request, authRequest);
    Authentication authentication = null;
    try
    {
      authentication = getAuthenticationManager().authenticate(authRequest);
    }
    catch (Exception e)
    {
      throw new AuthenticationServiceException("用户名密码错误！");
    }
    UserInfo userDetails = (UserInfo)authentication.getPrincipal();
    if (!userDetails.getRolesName().contains("ROLE_STUDENT")) {
      throw new AuthenticationServiceException("管理用户请从后台管理页面登录！");
    }
    return authentication;
  }
  
  protected void checkValidateCode(HttpServletRequest request)
  {
    HttpSession session = request.getSession();
    
    String sessionValidateCode = obtainSessionValidateCode(session);
    

    String validateCodeParameter = obtainValidateCodeParameter(request);
    if ((StringUtils.isEmpty(validateCodeParameter)) || (!sessionValidateCode.equalsIgnoreCase(validateCodeParameter))) {
      throw new AuthenticationServiceException("验证码错误！");
    }
  }
  
  protected String obtainSeriNoParameter(HttpServletRequest request)
  {
    Object obj = request.getParameter("j_seri_no");
    return null == obj ? "" : obj.toString().trim().toUpperCase();
  }
  
  protected String obtainFlagParameter(HttpServletRequest request)
  {
    Object obj = request.getParameter("j_flag");
    return null == obj ? "" : obj.toString().trim().toUpperCase();
  }
  
  protected String obtainValidateCodeParameter(HttpServletRequest request)
  {
    Object obj = request.getParameter("validate_code");
    return null == obj ? "" : obj.toString().trim().toUpperCase();
  }
  
  protected String obtainSessionValidateCode(HttpSession session)
  {
    return null;
  }
  
  protected String obtainPassword(HttpServletRequest request)
  {
    Object obj = request.getParameter("j_password");
    return null == obj ? "" : obj.toString();
  }
  
  protected String obtainUsername(HttpServletRequest request)
  {
    Object obj = request.getParameter("j_username");
    return null == obj ? "" : obj.toString().trim().toLowerCase();
  }
}
